using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class MainWeapon : MonoBehaviour
{
    //FIELDS
    public float m_RecoilForce = 5.0f;
    public float m_EnergyLevel = 10.0f;

    private float m_CurrentEnergyLevel = 0;
    private float m_EnergyPerShot = 2.5f;
    private float m_RegenerationSpeed = 2.0f;
    public float m_BlastForce = 1600f;

    private Vector3 m_WeaponDirection;

    public float FOVAngle = 10f;
    public float FOVDistance = 25f;

    private GameObject player;

    void Start()
    {
        player = GameObject.FindGameObjectWithTag("Player") as GameObject;

        m_CurrentEnergyLevel = m_EnergyLevel;
    }

    // Update is called once per frame
    void Update()
    {
        //When we fire, do pass the recoil to the character
        if (Input.GetMouseButtonDown(0) && m_CurrentEnergyLevel > 0)
        {
            //PLAYER ADJUSTMENTS
            //create perpendicular line with only the z info from the player
            Vector3 playerTarget = new Vector3(Camera.mainCamera.transform.position.x, Camera.mainCamera.transform.position.y, player.transform.position.z);
            //find the distance between the player and the camera
            float distance = Vector3.Distance(Camera.mainCamera.transform.position, playerTarget);
            //find the mousepos in world space based on the distance removed from camera
            Vector3 mouseWP = Camera.mainCamera.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, Mathf.Abs(distance) - 0.4f));

            //create difference vector
            m_WeaponDirection = mouseWP - player.transform.position;

            //IF OUR CHARACTER IS NOT GROUNDED, we don't give an extra upwards recoil
            if (player.GetComponent<CharacterController>().isGrounded != true)
                m_WeaponDirection.y = 0;

            //pass on the recoil to the charactercontroller
            player.GetComponent<Pawn>().GiveRecoil(m_RecoilForce, -m_WeaponDirection);

            //when weapon is being used substract some energy to avoid continues shooting
            m_CurrentEnergyLevel -= m_EnergyPerShot;


            //LEVEL OBJECT ADJUSTMENTS
            //check if objects are in our weapon FOV
            GameObject[] moveableBoxes = GameObject.FindGameObjectsWithTag("MoveableBlock");
            List<GameObject> pushedBoxes = new List<GameObject>();

            foreach (GameObject go in moveableBoxes)
            {
                if (CheckObjectInFOV(go) == true)
                {
                    go.renderer.material.color = new Color(1,0,0);
                    //PushObject(go);
                    pushedBoxes.Add(go);
                }
            }

            PushObject(pushedBoxes);
            pushedBoxes.Clear();
        }
        else //when not firing
        {
            //regenerate energy
            if (m_CurrentEnergyLevel < m_EnergyLevel)
                m_CurrentEnergyLevel += Time.deltaTime * m_RegenerationSpeed;
        }

        //Debug.Log("Weapon energy is: " + m_CurrentEnergyLevel);
    }

    bool CheckObjectInFOV(GameObject go)
    {
        if (go == null)
            return false;

        //1. calculate difference vector from object to weapon
        Vector3 differenceVector = this.transform.position - go.transform.position;
        //2. store the length so we can check if it is our range
        float length = Vector3.Magnitude(differenceVector);

        //first check if length is not bigger then our FOVDistance
        //if not, continue calculations else our foreach
        if (length > FOVDistance)
            return false;

        //3. get dot product between calculated vector and the angle of our gun
        float angle = Vector3.Dot(-differenceVector, Vector3.Normalize(m_WeaponDirection));
        //4. change our FOVAngle(half of it) into radians 
        float FOVAngleRadians = (FOVAngle / 2) * Mathf.Deg2Rad;

        //5. determine if the object is in our FOV
        if (angle >= Mathf.Cos(FOVAngleRadians))
            return true;
        else
            return false;
    }

    void PushObject(List<GameObject> list)
    {
        if (list != null && list.Count > 0)
        {
            foreach (GameObject go in list)
            {
                float distance = m_WeaponDirection.magnitude;
                float totalForce = m_BlastForce / (distance * distance);
                Vector3 pushForce = m_WeaponDirection.normalized * m_BlastForce;

                //adjust velocity directly because AddForce does wierd stuff :)
                //go.rigidbody.velocity = transform.TransformDirection(pushForce);
                go.rigidbody.velocity += pushForce * Time.deltaTime;

                //Debug.Log("velocity: " + go.rigidbody.velocity);
            }
        }
    }

    public float GetCurrentEnergy()
    {
        return m_CurrentEnergyLevel;
    }
}